#!/usr/bin/env python3
"""
比特币挖矿程序 - 简单实现
"""

import hashlib
import time
import random
import struct
import binascii
from datetime import datetime

class Block:
    """比特币区块结构"""
    def __init__(self, version=1, prev_block_hash='0'*64, merkle_root=None, 
                 timestamp=None, bits=0x1d00ffff, nonce=0):
        self.version = version
        self.prev_block_hash = prev_block_hash
        self.merkle_root = merkle_root or '0'*64
        self.timestamp = timestamp or int(time.time())
        self.bits = bits  # 难度目标
        self.nonce = nonce
    
    def get_header(self):
        """获取区块头"""
        header = struct.pack("<L", self.version)                       # 版本号 4字节
        header += bytes.fromhex(self.prev_block_hash)[::-1]            # 前一个区块的哈希 32字节
        header += bytes.fromhex(self.merkle_root)[::-1]                # Merkle根 32字节
        header += struct.pack("<L", self.timestamp)                    # 时间戳 4字节
        header += struct.pack("<L", self.bits)                         # 难度目标 4字节
        header += struct.pack("<L", self.nonce)                        # 随机数 4字节
        return header
    
    def calculate_hash(self):
        """计算区块头的哈希值"""
        header = self.get_header()
        hash_result = hashlib.sha256(hashlib.sha256(header).digest()).digest()
        return binascii.hexlify(hash_result[::-1]).decode('utf-8')
    
    def __str__(self):
        return (f"Block:\n"
                f"  Version: {self.version}\n"
                f"  Previous Hash: {self.prev_block_hash}\n"
                f"  Merkle Root: {self.merkle_root}\n"
                f"  Time: {datetime.fromtimestamp(self.timestamp).strftime('%Y-%m-%d %H:%M:%S')}\n"
                f"  Bits: {hex(self.bits)}\n"
                f"  Nonce: {self.nonce}")


class BitcoinMiner:
    """比特币挖矿器"""
    def __init__(self, difficulty_bits=24):
        self.difficulty_bits = difficulty_bits
        # 计算目标值: 2^(256-difficulty_bits) - 1
        self.target = 2 ** (256 - difficulty_bits)
    
    def mine(self, block, max_nonce=1000000):
        """
        挖矿过程 - 寻找符合难度要求的nonce值
        返回: (是否成功, nonce, 哈希值)
        """
        print(f"开始挖矿 [难度: {self.difficulty_bits} bits]...")
        print(f"目标: 找到哈希值小于 {hex(self.target)}")
        
        start_time = time.time()
        for nonce in range(max_nonce):
            if nonce > 0 and nonce % 10000 == 0:
                # 每10000次尝试显示一次进度
                elapsed = time.time() - start_time
                hashrate = nonce / elapsed if elapsed > 0 else 0
                print(f"已尝试 {nonce} 次，哈希率: {hashrate:.2f} H/s")
            
            # 设置nonce值
            block.nonce = nonce
            
            # 计算哈希
            hash_hex = block.calculate_hash()
            
            # 将哈希转为整数，与目标值比较
            hash_int = int(hash_hex, 16)
            
            if hash_int < self.target:
                # 找到了符合条件的哈希
                elapsed = time.time() - start_time
                hashrate = nonce / elapsed if elapsed > 0 else 0
                print(f"找到有效哈希！")
                print(f"  经过时间: {elapsed:.2f} 秒")
                print(f"  尝试次数: {nonce}")
                print(f"  哈希率: {hashrate:.2f} H/s")
                print(f"  哈希值: {hash_hex}")
                return True, nonce, hash_hex
        
        print("没有找到有效哈希，达到最大尝试次数。")
        return False, nonce, None


def main():
    # 创建一个新区块
    print("创建新区块...")
    new_block = Block(
        version=1,
        prev_block_hash="0000000000000000000000000000000000000000000000000000000000000000",
        merkle_root="4a5e1e4baab89f3a32518a88c31bc87f618f76673e2cc77ab2127b7afdeda33b",
        timestamp=int(time.time())
    )
    print(new_block)
    
    # 创建矿工并开始挖矿
    # 为了演示方便，这里使用较低的难度，真实比特币网络难度要高得多
    difficulty = 16  # 为了演示，使用较小的难度
    miner = BitcoinMiner(difficulty_bits=difficulty)
    
    success, nonce, hash_hex = miner.mine(new_block)
    
    if success:
        print("\n区块成功开采!")
        new_block.nonce = nonce
        print(new_block)
        print(f"区块哈希: {hash_hex}")
    else:
        print("\n挖矿失败，请尝试增加最大尝试次数或降低难度。")


if __name__ == "__main__":
    try:
        main()
    except KeyboardInterrupt:
        print("\n程序被用户中断。")
        print("挖矿已停止。")
